﻿/*
 * DATAFLOWCORE
 * 
Copyright 2012 - Mindstorm Multitouch Limited

Author - Bertrand Nouvel

DataFlowCore is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

DataFlowCore is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser Public License for more details.
*/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Bson;

namespace DFlow
{
    public abstract class TrainableNode : PersistentNode
    {
        public new class Parameters : PersistentNode.Parameters
        {
            public float traininablenode_amount = 100; // use negative amout for percentage of the training set
            public int trainablenode_reset = 0;
        }

        int _numexamples = 0;
        public int numexamples { get { return _numexamples; } }
        bool trained = false;

        public virtual bool IsTrained()
        {
            return trained;
        }


        public virtual bool IsTrainingDone()
        {
            Parameters p = GetParameters() as Parameters;
            return (numexamples > p.traininablenode_amount);
        }

        public virtual void TrainingInit() { }
        public abstract void TrainingProcess();
        public abstract void TrainingFinalize();
        public abstract void RunningProcess();

        public override void UpdateParameters(object doc)
        {
            base.UpdateParameters(doc);
            // try to load indicated model
            Parameters p = GetParameters() as Parameters;
            if (p.trainablenode_reset != 0)
            {

                p.trainablenode_reset = 0;
            }

        }

        public override void Process()
        {
            if (!IsTrained())
            {
                TrainingProcess();
                _numexamples++;
                if (IsTrainingDone())
                {
                    TrainingFinalize();
                    trained = true;
                }
                throw new DFlow.NodeInTrainingModeException();
            }
            else
            {
                RunningProcess();
            }
        }
    }

    public class NodeInTrainingModeException : System.Exception
    {
       // float percentDone = -1;
    }


}
